#include "common.h"
S4B Send(PMESSAGE pmessage,U4B type)
{

   PPROCESS ppro=process;
 //  if((U4B)ppro==0Xa00000)Print("user send..");
   while(ppro!=PTR_INVALID && ppro->p_pid!=pmessage->destination &&ppro->p_pprocessnext!=process)
   { 
      ppro=ppro->p_pprocessnext;
   }

   
   if(ppro==PTR_INVALID) 
   { Print("failure1\n\n"); return ARTIST_ERROR_PROCESSMECHANISMERROR;}
   if( ppro->p_pmessage==PTR_INVALID )
   {
    Print("failure2\n\n"); return ARTIST_ERROR_MESSAGEMECHANISMERROR;
   }
   if( ppro->p_pid!=pmessage->destination)
   {
    Print("failure3 destination:%X\n\n",pmessage->destination); return ARTIST_ERROR_IPCDESTINATIONNOTEXIST;
   }

   /*We should know who send the message.*/
   if(ReenterKernel>0)
     { pmessage->sourcepid=(U4B)INTERRUPT;}
   else
     { pmessage->sourcepid=WhoRunning->p_pid;  }


   
   U4B number= ppro->p_messageplace+1;
   number=number%ppro->p_messagelimit; 
   
   if(number==ppro->p_messageget)
   {
     if(type==SEND_MUSTARRIVE && ReenterKernel<=0) /*the sender is a process.*/
    /*

      The interrupt can't send the message 
      which must arrive at the destination 
      because the interrupt has no PCB

    */
     {

        WhoRunning->p_messageshack=*pmessage;
        (WhoRunning->p_messageshack).destination=(U4B)heartbeat;/*the variable destination change its usage.*/
        PPROCESS messagenode=ppro->p_messageheader;
        if(messagenode==PTR_INVALID)
		{
		   ppro->p_messageheader=WhoRunning;
		   WhoRunning->p_messagequeue=PTR_INVALID;
		   return ARTIST_ERROR_OK;
		}
        for(;messagenode->p_messagequeue!=PTR_INVALID;messagenode=messagenode->p_messagequeue);
        messagenode->p_messagequeue=WhoRunning;
        WhoRunning->p_messagequeue=PTR_INVALID;
        WhoRunning->p_state=STATE_WAIT;
        WhoRunning->p_waitsource=ppro->p_pid;
        WhoRunning->p_waitsignal=SIGNAL_SAFESEND;
        Schedule();
        return ARTIST_ERROR_OK;
     }
     else
      {Print("failure4\n\n");  return ARTIST_ERROR_MESSAGEINTERRUPTFAILURE;}
   }
   

   ppro->p_pmessage[ppro->p_messageplace]=*pmessage;
   (ppro->p_pmessage[ppro->p_messageplace]).destination=(U4B)heartbeat;
 //  Print("the sender:%s,the message:%X\n\n",WhoRunning->p_name,(*pmessage).type);
   ppro->p_messageplace=number;
   return ARTIST_ERROR_OK;
}
S4B SendMessage(PMESSAGE pmessage)
{
    S4B value;
    SystemCallInterrupt((U4B)SYSCALL_SENDMESSAGE,(U4B)pmessage,SEND_MAYLOSE,(U4B)&value);
    return value;
}
S4B SafeSend(PMESSAGE pmessage)
{
   S4B value;
   SystemCallInterrupt((U4B)SYSCALL_SENDMESSAGE,(U4B)pmessage,SEND_MUSTARRIVE,(U4B)&value);
   return value;
}
